package settings

import (
	"crypto/md5"
	"errors"
	"fmt"
	"gitee.com/Luna-CY/hui-hui/internal/configure"
	"gitee.com/Luna-CY/hui-hui/server/http/response"
	"github.com/gin-gonic/gin"
	"github.com/pquerna/otp/totp"
)

type SetAuthRequest struct {
	Type     string `json:"type" validate:"required" enums:"fixed,email-code,totp" binding:"required,oneof=fixed email-code totp"` // 验证类型
	Password string `json:"password" validate:"optional" binding:"required_if=Type fixed,omitempty,min=6,max=32"`                  // 密码
	Email    string `json:"email" validate:"optional" binding:"required_if=Type email-code,omitempty,email"`                       // 接收验证码的邮件地址
	Secret   string `json:"secret" validate:"optional" binding:"required_if=Type totp,omitempty"`                                  // 用于生成验证码的Secret字符串
	Code     string `json:"code" validate:"optional" binding:"required_if=Type totp,omitempty,min=6,max=6"`                        // TOTP临时验证码，用于验证Secret是否有效
}

func (cls *Settings) SetAuth(c *gin.Context) (int, any, error) {
	var body = SetAuthRequest{}
	if err := c.ShouldBindJSON(&body); nil != err {
		return response.InvalidRequest, nil, err
	}

	switch configure.AuthenticationType(body.Type) {
	case configure.AuthenticationTypeFixed:
		configure.Configure.Server.Authentication.Type = configure.AuthenticationTypeFixed
		configure.Configure.Server.Authentication.Password = fmt.Sprintf("%x", md5.Sum([]byte(body.Password)))

	case configure.AuthenticationTypeEmailCode:
		if "" == configure.Configure.Smtp.Host || 0 == configure.Configure.Smtp.Port || "" == configure.Configure.Smtp.From {
			return response.InvalidRequest, nil, errors.New("SMTP服务器配置无效，请先完成SMTP服务器的配置后启用邮件验证码")
		}

		configure.Configure.Server.Authentication.Type = configure.AuthenticationTypeEmailCode
		configure.Configure.Server.Authentication.Email = body.Email
	case configure.AuthenticationTypeTOTP:
		configure.Configure.Server.Authentication.Type = configure.AuthenticationTypeTOTP
		configure.Configure.Server.Authentication.Secret = body.Secret

		if !totp.Validate(body.Code, configure.Configure.Server.Authentication.Secret) {
			return response.InvalidRequest, nil, errors.New("TOTP验证码错误")
		}
	}

	if err := configure.SyncToDisk(); nil != err {
		return response.Unknown, nil, err
	}

	return response.Ok, nil, nil
}
